package server

import (
	ginzap "github.com/gin-contrib/zap"
	"github.com/gin-gonic/gin"
	"gitee.com/youbeiwuhuan/go-xxljob-executor/biz"
	. "gitee.com/youbeiwuhuan/go-xxljob-executor/biz/model"
	. "gitee.com/youbeiwuhuan/go-xxljob-executor/global"
	"gitee.com/youbeiwuhuan/go-xxljob-executor/utils/https"
	"net/http"
	"strconv"
	"time"
)

type ExecutorBizServer struct {
	server      *gin.Engine
	ip          string
	accessToken string
	port        int32
	executorBiz biz.ExecutorBiz
}

func NewExecutorBizServer(ip string, port int32, accessToken string, executorBiz biz.ExecutorBiz) *ExecutorBizServer {
	router := gin.New()

	// 使用zap日志库
	router.Use(ginzap.Ginzap(Logger, time.RFC3339, true))
	router.Use(ginzap.RecoveryWithZap(Logger, true))

	//全局异常处理
	router.Use(Recovery)

	//404 處理
	router.NoRoute(Deal404)
	router.NoMethod(Deal404)

	//accessToken 处理
	router.Use(validAccessTokenHandlerFunc(accessToken))

	initExecutorBizRouter(executorBiz, router)

	return &ExecutorBizServer{
		server:      router,
		ip:          ip,
		accessToken: accessToken,
		port:        port,
		executorBiz: executorBiz,
	}

}

func initExecutorBizRouter(executorBiz biz.ExecutorBiz, router *gin.Engine) {
	router.POST("/beat", func(c *gin.Context) {
		c.JSON(http.StatusOK, executorBiz.Beat())

	})

	router.POST("/idleBeat", func(c *gin.Context) {
		idleBeatParam := IdleBeatParam{}
		err := c.ShouldBind(&idleBeatParam)
		if nil != err {
			c.JSON(http.StatusOK, ReturnT{
				Code: FAIL_CODE,
				Msg:  err.Error(),
			})
			return
		}
		c.JSON(http.StatusOK, executorBiz.IdleBeat(idleBeatParam))
	})

	router.POST("/run", func(c *gin.Context) {
		triggerParam := TriggerParam{}
		err := c.ShouldBind(&triggerParam)
		if nil != err {
			c.JSON(http.StatusOK, ReturnT{
				Code: FAIL_CODE,
				Msg:  err.Error(),
			})
			return
		}
		c.JSON(http.StatusOK, executorBiz.Run(triggerParam))
	})

	router.POST("/kill", func(c *gin.Context) {
		killParam := KillParam{}
		err := c.ShouldBind(&killParam)
		if nil != err {
			c.JSON(http.StatusOK, ReturnT{
				Code: FAIL_CODE,
				Msg:  err.Error(),
			})
			return
		}
		c.JSON(http.StatusOK, executorBiz.Kill(killParam))
	})

	router.POST("/log", func(c *gin.Context) {

		logParam := LogParam{}
		err := c.ShouldBind(&logParam)
		if nil != err {
			c.JSON(http.StatusOK, ReturnT{
				Code: FAIL_CODE,
				Msg:  err.Error(),
			})
			return
		}
		c.JSON(http.StatusOK, executorBiz.Log(logParam))
	})

}

//验证accessToken逻辑
func validAccessTokenHandlerFunc(accessToken string) gin.HandlerFunc {
	return func(c *gin.Context) {

		accessTokenReq := c.GetHeader(https.XXL_JOB_ACCESS_TOKEN)
		if accessTokenReq == accessToken {
			c.Next()
			return
		}

		c.JSON(http.StatusOK, ReturnT{
			Code: FAIL_CODE,
			Msg:  "accessToken error",
		})
		c.Abort()
	}
}

func (t *ExecutorBizServer) Start() {
	go func() {
		Logger.Info("------ExecutorBizServer init ,listen on port " + strconv.Itoa(int(t.port)) + "--------")
		t.server.Run(t.ip + ":" + strconv.Itoa(int(t.port)))

	}()
}

func (t *ExecutorBizServer) Stop() {

}
